热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

文中|数目_Redis批量操作详解及性能分析

篇首语:本文由编程笔记#小编为大家整理,主要介绍了Redis批量操作详解及性能分析相关的知识,希望对你有一定的参考价值。通过mget批量执行指令可以节约网络连接和数据传输

篇首语:本文由编程笔记#小编为大家整理,主要介绍了Redis批量操作详解及性能分析相关的知识,希望对你有一定的参考价值。


通过mget批量执行指令可以节约网络连接和数据传输开销,在高并发场景下可以节约大量系统资源。本文中,我们更进一步,比较一下redis提供的几种批量执行指令的性能。


1. 为什么需要批量执行redis指令

众所周知,Redis协议采取的是客户端-服务器方式,即在一次round trip中,客户端发送一条指令,服务端解析指令并执行,然后向客户端返回结果。这是一种典型的tcp交互方式。

粗略的分,客户端发起一次Redis请求主要有如下开销:


  • socket IO导致的上下文切换开销 (严重读写系统开销)

熟悉OS/Linux的童鞋都知道,一次redis请求在客户端和服务端分别至少会存在一次read()和一次write(),作为系统调用,read/write的成本高于普通的函数调用,因此,在单个命令重复调用场景下,大量的read/write系统调用会产生明显的系统开销。


  • 指令执行开销 (轻微指令开销)

Redis采用C实现,使用了轻量级的hash表、skipList跳表等数据结构实现了高效的缓存。因此,单条执行大多数指令的成本非常低。因此,相对而言,IO的开销显得更加无法忽略。


  • (高并发下)资源竞争和系统调度调度开销 (Redis竞争抖动)

客户端的影响非常明显。在高压力下,如果采用循环(loop)方式调用多次指令来完成某个服务请求,那么在高并发下,多个请求会在多个线程中同时竞争redis连接资源多次,导致连接池压力增加,线程上下文切换更加频发,最终会导致请求RTT(round-trip time)急剧恶化。如果每个请求只抢占一次redis连接并通过批量执行的方式一次处理多个请求,则单次请求的RTT会有显著提升。

在服务端,因为我们通常将redis绑定到CPU(不管是通过物理机还是通过docker),因此一般而言不存在系统调度/资源竞争的开销。但是由于redis对QPS敏感,如果因为客户端使用不合理而造成QPS放大效应,则redis可能更早触及性能瓶颈而导致系统响应严重下降。

笔者曾经在一次性能调优中发现,每次服务请求访问redis次数高达数十次,使得redis请求次数达到服务QPS的数十倍,触发了redis服务器的极限(大概5~10万QPS)而导致服务性能低下,多个请求对redis连接池进行了激烈竞争,并且由于redis响应速度的下降导致大量线程在获取连接处阻塞并频繁进行线程切换。在改进实现采用了批量指令处理后,服务性能瞬间达到了数十倍的提升。因此,如果每次服务掉用需要触发多次redis请求,合理地适用批量执行技术,可以使系统运行更加有效,数据吞吐得到明显提升。


2. redis批量指令介绍

2.1. 批量命令即redis对应的命令


  • mget(适用于string类型)
  • mset(适用于string类型)
  • hmget(适用于hash类型)
  • hmset(适用于hash类型)

严格来说上述命令不属于批量操作,而是在一个指令中处理多个key。


  • 优势:性能优异,因为是单条指令操作,因此性能略优于其他批量操作指令
  • 劣势:批量命令不保证原子性,存在部分成功部分失败的情况,需要应用程序解析返回的结果并做相应处理   批量命令在key数目巨大时存在RRT与key数目成比例放大的性能衰减,会导致单实例响应性能(RRT)严重下降

2.2 管道 pipeline

管道(pipelining)方式意味着客户端可以在一次请求中发送多个命令。


  • 优势:

  1. 通过管道,可以将多个redis指令聚合到一个redis请求中批量执行
  2. 可以使用各种redis命令,使用更灵活
  3. 客户端一般会将命令打包,并控制每个包的大小,在执行大量命令的场景中,可以有效提升运行效率
  4. 由于所有命令被分批次发送到服务器端执行,因此相比较事务类型的操作先逐批发送,再一次执行(或取消),管道拥有微弱的性能优势

  • 劣势:

  1. 没有任何事务保证,其他client的命令可能会在本pipeline的中间被执行

2.3 事务操作

事务(Transactions)操作允许在一步中执行一组redis操作,并对这一组redis命令有如下保证:


  1. 同一个事务中的所有命令会被串行地逐一执行。不可能出现有任何来自其他client的命令在这组命令中间被执行。
  2. 单个事务的所有命令,或者被全部执行,或者一个也不会被执行,因此事务保证了redis操作的原子性。命令EXEC触发事务中所有命令的执行,因此如果一个client在事务上下文中丢失了连接,那么不会有任何一条命令被执行;相反如果client已经调用了EXEC,那么所有命令都会被执行。

  3. 当使用append-only文件时,Redis保证仅使用一个write(2)系统调用来将事务结果写入磁盘。然而如果Redis server崩溃或者被系统管理员使用hard方式kill了进程,那么还是有可能只写入了部分操作。Redis在重启时可以检测到这一问题,并以error退出。这时,可以使用redis-check-aof工具来对append-only文件进行修复,它将会删除部分写入的事务这样server就可以启动了。


  • 优势:

  1. 事务的执行具备原子性,即全部被执行或全部不执行,并且在持久化时也具备原子性
  2. 可以使用WATCH提供的乐观锁机制保证命令执行的排他性

  • 劣势:

  1. 事务的所有命令会分批发送给redis实例,redis返回+QUEUED,表示命令已入列,但是不会执行任何命令。在收到EXEC命令时,一次执行本事务的所有命令。因此事务的性能略低于pipeline,但是相差不多。

  2. 在keys竞争激烈时,WATCH提供的乐观锁由于竞争过多而性能低下,应该尽量避免。


2.4 基于管道的事务

在Redis中,管道是通过RESP,即redis协议来实现的,它允许在一个消息包中按照指定格式传递多个命令。而事务是通过命令实现的,因此管道和事务之间并不冲突,事务可以承载与管道之上。在某些场景,需要在一次请求处理中发起多次事务的场景下,通过引入管道,可以获得略高于单独执行多次事务的性能,但是两者的差距非常小,小到可以忽略。


3. 压测用例分析

针对上述4种批量操作,设计如下case:


  • 条件:在本地单机redis中创建1,000,000对key-value,key长8字节,value长5字节
  • 测试过程:

  1. 使用set/mset/pipeline/transaction/transaction in pipeline这五种方式分别重新设置所有key的值,记录各自的运行时长
  2. 使用get/mget/pipeline/transaction/transaction in pipeline这五种方式分别遍历所有key的值,记录各自的运行时长

单位:ms


3.1 SET性能压测结果


3.2 GET性能压测结果


3.3 结论

从上述测试结果中可以看出,不同的处理方式,最终性能曲线基本一致。


  • mset性能最好,吞吐量最高,因为mset是作为单条命令执行,在命令解析和执行上都更有效率
  • pipeline好于transaction in pipeline,因为事务会导致命令入列和出列会稍许浪费cpu时间
  • transaction in pipeline微弱领先于transaction,但是几乎没有区别,可以理解为pipeline在命令传输上更有效率。
  • 总得来说,在批量模式下,四种操作都比普通的get/set性能上有几大的提升。
  • 在当前生产环境中使用较多的Redis Cluster环境中,上述四种批量操作的使用场景都比较有限,其中transaction不支持,pipeline建议仅用于单slot且目前支持的客户端很少,mget/mset也仅仅可以操作于单slot中的key。

推荐阅读
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • 本文介绍了使用PHP实现断点续传乱序合并文件的方法和源码。由于网络原因,文件需要分割成多个部分发送,因此无法按顺序接收。文章中提供了merge2.php的源码,通过使用shuffle函数打乱文件读取顺序,实现了乱序合并文件的功能。同时,还介绍了filesize、glob、unlink、fopen等相关函数的使用。阅读本文可以了解如何使用PHP实现断点续传乱序合并文件的具体步骤。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • Linux如何安装Mongodb的详细步骤和注意事项
    本文介绍了Linux如何安装Mongodb的详细步骤和注意事项,同时介绍了Mongodb的特点和优势。Mongodb是一个开源的数据库,适用于各种规模的企业和各类应用程序。它具有灵活的数据模式和高性能的数据读写操作,能够提高企业的敏捷性和可扩展性。文章还提供了Mongodb的下载安装包地址。 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • 本文介绍了高校天文共享平台的开发过程中的思考和规划。该平台旨在为高校学生提供天象预报、科普知识、观测活动、图片分享等功能。文章分析了项目的技术栈选择、网站前端布局、业务流程、数据库结构等方面,并总结了项目存在的问题,如前后端未分离、代码混乱等。作者表示希望通过记录和规划,能够理清思路,进一步完善该平台。 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • 如何在服务器主机上实现文件共享的方法和工具
    本文介绍了在服务器主机上实现文件共享的方法和工具,包括Linux主机和Windows主机的文件传输方式,Web运维和FTP/SFTP客户端运维两种方式,以及使用WinSCP工具将文件上传至Linux云服务器的操作方法。此外,还介绍了在迁移过程中需要安装迁移Agent并输入目的端服务器所在华为云的AK/SK,以及主机迁移服务会收集的源端服务器信息。 ... [详细]
author-avatar
男人还是闷骚点好
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有